package com.niknik.woody.utils.wunit.junit.matcher;

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.mockito.ArgumentMatcher;

import static java.text.MessageFormat.format;

public class IsEx
    extends ArgumentMatcher<Throwable> {

  private final Class clazz;
  private final String msg;

  private IsEx(Class clazz, String msg) {
    if (null == clazz) {
      throw new IllegalArgumentException("Expected class instance cannot be null");
    }
    this.clazz = clazz;
    this.msg = msg;
  }

  @Override
  public boolean matches(Object exObj) {
    if (exObj == null) {
      return false;
    }
    if (!(exObj instanceof Throwable)) {
      throw new IllegalArgumentException("Expected a subclass of java.lang.Throwable");
    }
    Throwable ex = (Throwable) exObj;
    return clazz.isInstance(ex) && msg.equals(ex.getMessage());
  }

  @Override
  public void describeTo(Description descr) {
    descr.appendText(format("{0}({1}, ''{2}'')", IsEx.class.getSimpleName(), clazz.getName(), msg));
  }

  @Factory
  public static IsEx isEx(Class clazz, String msg) {
    return new IsEx(clazz, msg);
  }

  @Factory
  public static IsEx isArgEx(String msg) {
    return isEx(IllegalArgumentException.class, msg);
  }

  @Factory
  public static IsEx isStateEx(String msg) {
    return isEx(IllegalStateException.class, msg);
  }

  @Factory
  public static IsEx isAssertionEx(String msg) {
    return isEx(AssertionError.class, msg);
  }
}